﻿using Microsoft.Win32;
using Newtonsoft.Json;
using Pay.Window.Data.Model;
using System;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;
using System.Linq;
using System.Configuration;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Drawing;
using Pay.Window.Data.Utilitys;
using Pay.Window.Data.Dto;
using Pay.Http.Utilitys;
using System.Net.Http;
using Pay.Common;
using System.Text;

namespace Pay.Window.Data
{
    public partial class DefaultForm : Form
    {
        #region 私有成员

        private ConfigModel CONFIG = null;

        /// <summary>
        /// 计时器
        /// </summary>
        private bool TIMER_START = true;

        /// <summary>
        /// 默认为true,自动执行
        /// </summary>
        private bool SYS_STATUS = true;

        /// <summary>
        /// 登录验证码
        /// </summary>
        private string LOGIN_CODE = string.Empty;

        /// <summary>
        /// 启动账号
        /// </summary>
        private static WindowAlipayAccountOutput Account { get; set; }

        /// <summary>
        /// 键盘驱动
        /// </summary>
        /// <param name="bVk"></param>
        /// <param name="bScan"></param>
        /// <param name="dwFlags"></param>
        /// <param name="dwExtraInfo"></param>
        [DllImport("user32.dll", EntryPoint = "keybd_event")]
        public static extern void keybd_event(
            byte bVk,
            byte bScan,
            int dwFlags,
            int dwExtraInfo
        );

        #endregion

        #region Init

        /// <summary>
        /// 窗体实例化
        /// </summary>
        public DefaultForm(WindowAlipayAccountOutput account)
        {
            InitializeComponent();
            Account = account;
        }

        /// <summary>
        /// 窗体初始化
        /// </summary>
        private void DefaultForm_Init()
        {
            #region 注册IE版本

            //RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION", true);
            //if (key != null)
            //{
            //    key.SetValue("XXX.exe", 11001, RegistryValueKind.DWord);
            //    key.SetValue("XXX.vshost.exe", 11001, RegistryValueKind.DWord);//调试运行需要加上，否则不起作用
            //}

            //key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION", true);
            //if (key != null)
            //{
            //    key.SetValue("XXX.exe", 11001, RegistryValueKind.DWord);
            //    key.SetValue("XXX.vshost.exe", 11001, RegistryValueKind.DWord);//调试运行需要加上，否则不起作用
            //}

            #endregion

            Text += $"系统账号:{Account.SystemAccount},支付宝账号:{Account.AlipayAccount}";

            // 关闭线程安全检查
            CheckForIllegalCrossThreadCalls = false;

            // 初始化配置
            var configText = File.ReadAllText(ConfigurationManager.AppSettings["configPath"]);
            CONFIG = JsonConvert.DeserializeObject<ConfigModel>(configText ?? "");

            // 初始化web
            tbUrl.Text = CONFIG.DefaultLinks.Login.Link;
            web.ScriptErrorsSuppressed = true;
            webGo(tbUrl.Text);
            ShowWebb(false);

            // 初始化timer
            timerClick.Interval = CONFIG.Timer?.Interval ?? 3000;
            timerClick.Enabled = true;

            timerService.Interval = 1000 * 10;
            timerService.Enabled = true;

            // 初始化按钮
            btnStart.Text = TIMER_START == true ? "已开启" : "已关闭";

            timerLogin.Interval = 1000;
            timerLogin.Enabled = false;

            // 开启日志记录滚动条
            tbLog.ScrollBars = ScrollBars.Vertical;
            tbLog.MaxLength = 50;

            // 初始化数据
            DataHelper.Init();

            AddLog("组建初始化完成");
        }

        /// <summary>
        /// 窗体加载完成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DefaultForm_Load(object sender, EventArgs e)
        {
            DefaultForm_Init();
        }

        /// <summary>
        /// 窗体关闭事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DefaultForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.Exit();
        }

        #endregion

        #region WebBrowser

        private void ShowWebb(bool show)
        {
            //web.Visible = show;
            //tbLog.Visible = !show;
            web.Visible = true;
            tbLog.Visible = true;
        }

        /// <summary>
        /// 设置Html元素value值
        /// </summary>
        /// <param name="element"></param>
        /// <param name="value"></param>
        private void HtmlInputValue(HtmlElement element, string value)
        {
            if (element == null)
                return;

            WindowFocus();

            HtmlFocus(element);
            
            element.SetAttribute("value", value);

            // 驱动键盘输入
            keybd_event((byte)Keys.A, 0, 0, 0); // 按下
            keybd_event((byte)Keys.A, 0, 0x2, 0); //弹起

            // 驱动键盘输入
            keybd_event((byte)Keys.Back, 0, 0, 0); // 按下
            keybd_event((byte)Keys.Back, 0, 0x2, 0); //弹起

            // SendKeys.Send(value);


        }

        private void ReloadLoginImgCode()
        {
            // 如果是登录页面,获取图片验证码
            //var imgLoginCode = GetWebImage(web, web.Document.GetElementById("J-checkcode-img"));

            //pbLoginCode.Image = imgLoginCode;
        }

        private void LoginCodeClick()
        {
            web.Document.GetElementById("J-checkcode-img")?.InvokeMember("click");
            ReloadLoginImgCode();
        }

        private void WindowFocus()
        {
            this.Activate();
        }

        private void HtmlClick(HtmlElement element)
        {
            if (element == null)
                return;
            element.InvokeMember("click");
        }

        private void HtmlFocus(HtmlElement element)
        {
            if (element == null)
                return;
            element.InvokeMember("focus");
        }

        /// <summary>
        /// 页面导航跳转
        /// </summary>
        /// <param name="url"></param>
        private void webGo(string url)
        {
            if (url.Contains("http://") || url.Contains("https://"))
            {
                web.Url = new Uri(url);
            }
        }

        /// <summary>
        /// 页面加载完成事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void web_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            // 页面每次加载完成之后,系统自动设置为true,如果跳转到扫码
            ShowWebb(false);

            SysSwitchFormStatus(true);

            tbUrl.Text = web.Url.ToString();

            var pageModel = GetCurrentPageModel();

            if (pageModel != null)
            {
                if (pageModel.Page.IsOrder == true)
                {
                    await ApiSubmitAlipayOrders();
                }
            }
        }

        /// <summary>
        /// 登录操作信息
        /// </summary>
        private void InputUsername()
        {
            var doc = web.Document;

            var els = doc.GetElementsByTagName("span");

            for(var i = 0; i < els.Count; i++)
            {
                if (els[i].GetAttribute("className").Contains("sl-delect"))
                {
                    els[i].InvokeMember("click");
                }
            }

            HtmlInputValue(doc.GetElementById("J-input-user"), Account.AlipayAccount);
        }

        private void InputPassword()
        {
            var doc = web.Document;
            HtmlInputValue(doc.GetElementById("password_rsainput"), Account.AlipayPassword);
        }


        /// <summary>
        /// 返回指定WebBrowser中图片<IMG></IMG>中的图内容
        /// </summary>
        /// <param name="WebCtl">WebBrowser控件</param>
        /// <param name="ImgeTag">IMG元素</param>
        /// <returns>IMG对象</returns>
        private Image GetWebImage(WebBrowser WebCtl, HtmlElement ImgeTag)
        {
            mshtml.HTMLDocument doc = (mshtml.HTMLDocument)WebCtl.Document.DomDocument;
            mshtml.HTMLBody body = (mshtml.HTMLBody)doc.body;
            mshtml.IHTMLControlRange rang = (mshtml.IHTMLControlRange)body.createControlRange();
            mshtml.IHTMLControlElement Img = (mshtml.IHTMLControlElement)ImgeTag.DomElement; //图片地址

            Image oldImage = Clipboard.GetImage();
            rang.add(Img);
            rang.execCommand("Copy", false, null);  //拷贝到内存
            Image numImage = Clipboard.GetImage();
            try
            {
                Clipboard.SetImage(oldImage);
            }
            catch
            {

            }

            return numImage;
        }

        private void btnLoginCode_Click(object sender, EventArgs e)
        {
            //LOGIN_CODE = tbLoginCode.Text;
            InputLoginCode();
        }

        private void InputLoginCode()
        {
            var doc = web.Document;
            //HtmlInputValue(doc.GetElementById("J-input-checkcode"), LOGIN_CODE);

            doc.GetElementById("J-input-checkcode").SetAttribute("value", LOGIN_CODE);
        }

        private void SubmitLogin()
        {
            var doc = web.Document;
            // HtmlInputValue(doc.GetElementById("J-login-btn"), "{ENTER}");
            HtmlClick(doc.GetElementById("J-login-btn"));
        }

        /// <summary>
        /// 新窗口
        /// 防止弹窗
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void web_NewWindow(object sender, CancelEventArgs e)
        {
            e.Cancel = true;
            string url = this.web.StatusText;
            webGo(url);
        }

        private UrlConfigPagesModel GetCurrentPageModel()
        {
            if (web.Url == null)
                return null;

            // 获取当前页面链接
            var currentUrl = web.Url.ToString();

            // 获取当前页面配置
            var currentPage = CONFIG.Pages.FirstOrDefault(s => currentUrl.Contains(s.Page.Link));

            return currentPage;
        }

        #endregion

        #region Timer
        private int count = 0;

        private void timerLogin_Tick(object sender, EventArgs e)
        {
            try
            {
                if (TIMER_START != true)
                    return;

                if (SYS_STATUS != true)
                    return;

                if (web.Url == null)
                    return;

                var lis = web.Document.GetElementsByTagName("li");

                for (var i = 0; i < lis.Count; i++)
                {
                    if (lis[i].GetAttribute("data-status") != null && lis[i].GetAttribute("data-status").Contains("show_login"))
                    {
                        lis[i].InvokeMember("click");
                        break;
                    }
                }

                var codeDivEl = web.Document.GetElementById("J-checkcode");
                var codeEl = web.Document.GetElementById("J-input-checkcode");
                var codeDivClass = codeDivEl.GetAttribute("className");

                if (count == 0)
                {
                    InputUsername();
                    count++;
                    AddLog("支付宝登录中");
                }
                else if (count == 1)
                {
                    InputPassword();
                    count++;
                }
                else if (count == 2)
                {
                    if (codeDivClass.Contains("fn-hide")) // 如果验证码不存在,直接提交 fn-hide表示验证码被隐藏
                    {
                        SubmitLogin();
                        count = 0;
                    }
                    else
                    {
                        InputLoginCode();
                        count++;
                    }
                }
                else
                {
                    if (!codeDivClass.Contains("fn-hide")) // 如果验证码存在,必须要验证码长度为4之后,才能提交
                    {
                        if (codeEl.GetAttribute("value").ToString().Length == 4)
                        {
                            SubmitLogin();
                            count = 0;
                        }
                    }
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 计时器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerClick_Tick(object sender, EventArgs e)
        {
            if (TIMER_START != true)
                return;

            if (SYS_STATUS != true)
                return;

            if (web.Url == null)
                return;

            try
            {
                // 获取当前页面链接
                var currentUrl = web.Url.ToString();

                //// 获取当前页面配置
                //var currentPage = GetCurrentPageModel();

                //if (currentPage == null)
                //    return;


                // 获取当前页面配置
                var currentPage = GetCurrentPageModel();

                timerLogin.Enabled = false;

                if (tbUrl.Text.Split('?')[0].Contains(CONFIG.DefaultLinks.Login.Link))
                {
                    // 获取登录验证码
                    ReloadLoginImgCode();
                    // 如果是登录页面,开启登录专用timer
                    timerLogin.Enabled = true;
                }
                else if (tbUrl.Text.Contains(CONFIG.DefaultLinks.CheckSecurity.Link))
                {
                    AddLog("需要支付宝扫码通过安全校验");
                    // 如果扫码后,浏览器会自动跳转到相应页面,此时状态修改在跳转到其他页面后修改
                    SysSwitchFormStatus(false);
                    // 显示扫码界面
                    ShowWebb(true);
                }
                else if (currentPage == null) // 如果没有找到页面配置,回到首页
                {
                    webGo(CONFIG.DefaultLinks.Account.Link);
                }
                else
                {
                    // 获取当前页面拥有的链接,随机排序,随机点击链接
                    var currentLinks = currentPage.Links.OrderByDescending(s => Guid.NewGuid()).ToList();

                    if (CONFIG.DefaultLinks.Account.Link.Contains(currentPage.Page.Link))
                    {
                        AddLog("支付宝登录成功");
                    }

                    // 获取当前页面的所有链接
                    var links = web.Document.GetElementsByTagName("a");

                    if (links != null)
                    {
                        foreach (var currLink in currentLinks)
                        {
                            for (var i = 0; i < links.Count; i++)
                            {
                                if (links[i].GetAttribute("href").Contains(currLink.Link))
                                {
                                    links[i].InvokeMember("click");
                                    return;
                                }
                            }
                        }
                    }
                }
            }
            catch
            { }
        }

        private async void timerService_Tick(object sender, EventArgs e)
        {
            await ApiUpdateTime();
        }

        #endregion

        #region BUTTON

        private void btnStart_Click(object sender, EventArgs e)
        {
            SwitchFormStatus(!TIMER_START);
        }

        /// <summary>
        /// 手动切换状态
        /// </summary>
        /// <param name="status"></param>
        private void SwitchFormStatus(bool status)
        {
            TIMER_START = status;
            if (TIMER_START == true)
            {
                btnStart.Text = "已开启";
            }
            else
            {
                btnStart.Text = "已停止";
            }
        }

        /// <summary>
        /// 系统切换状态
        /// </summary>
        private void SysSwitchFormStatus(bool status)
        {
            SYS_STATUS = status;
        }

        private void btnUrlEnter_Click(object sender, EventArgs e)
        {
            webGo(tbUrl.Text);
        }

        private void btnRefImgCode_Click(object sender, EventArgs e)
        {

        }

        #endregion

        #region LOG

        private void AddLog(string log)
        {
            tbLog.AppendText(DateTime.Now.ToString("HH:mm:ss") + ":" + log + "\r\n");

            tbLog.Select(tbLog.Text.Length, 0);
            tbLog.ScrollToCaret();
        }

        #endregion

        #region API

        /// <summary>
        /// 提交订单信息
        /// </summary>
        /// <returns></returns>
        private async Task ApiSubmitAlipayOrders()
        {
            var newOrders = WebHelper.GetAlipayNewOrders(Account.SystemAccount, web);
            if (newOrders.Count > 0)
            {
                AddLog($"新增交易数据:{newOrders.Count}条,总金额{newOrders.Sum(s => s.Amount)}");
                var postData = JsonHelper.SerializeObject(newOrders);
                var output = await HttpClientHelper.PostJsonAsync<ApiOutput<UpdateTimeOutput>>("http://api.pay.com/api/aliService/OrderRecord", new StringContent(postData, Encoding.UTF8, "application/json"));
                if (output != null && output.Data != null)
                {
                    if (output.Data.Success == true)
                    {
                        DataHelper.UpdateDataSubmit(Account.SystemAccount);
                    }
                }
            }
        }

        /// <summary>
        /// 提交更新信息
        /// </summary>
        /// <returns></returns>
        private async Task ApiUpdateTime()
        {
            var input = new WindowUpdateTimeInput
            {
                SystemName = Account.SystemAccount
            };
            var updateTimeUrl = "http://api.pay.com/api/aliService/updatetime";
            var output = await HttpClientHelper.PostJsonAsync<ApiOutput<UpdateTimeOutput>>(updateTimeUrl, new StringContent(JsonHelper.SerializeObject(input), Encoding.UTF8, "application/json"));
            if (output != null && output.Data != null)
            {

            }
        }

        #endregion
    }
}